home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
comstr.exe
/
COMSTREA.CPP
< prev
next >
Wrap
Text File
|
1993-01-03
|
12KB
|
599 lines
#if !defined( __DOS_H )
#include <Dos.h>
#endif // __DOS_H
#if !defined( __COMSTREAM_H )
#include "Comstream.h"
#endif // __COMSTREAM_H
#if !defined( __TIMER_H )
#include "Timer.h"
#endif // __TIMER_H
#define TESTPORTBIT(x,y) (inportb(x) & y)
#define IER 1
#define IIR 2
#define LCR 3
#define LSR 5
#define MSR 6
#define MODEMFAIL 0
#define XMTEMPTY 2
#define READFULL 4
#define LINEFAIL 6
#define RXRDY 1
#define TBE 32
#define TXE 64
#define RTS 2
#define GP01 4
#define GP02 8
#define LOOPBACK 16
#define CTS 16
#define DLAB 128
ComDef::ComDef( int n )
{
if( n >= 0 && n < 4 )
{
unsigned far *pPort = (unsigned far *) MK_FP( 0, 0x400 );
portAddr = pPort[n];
}
else
portAddr = 0;
if( portAddr != 0 )
{
irqAddr = ( n & 1 ) ? 0x0B : 0x0C;
picMask = ( n & 1 ) ? 0x08 : 0x10;
oldhandler = getvect( irqAddr );
}
else
{
irqAddr = picMask = 0;
oldhandler = 0;
}
owner = 0;
}
ComDef::~ComDef()
{
clrCombuf();
}
void ComDef::setParams( int aPort, int aIRQ, int aMask )
{
if( owner != 0 ) return;
if( oldhandler && irqAddr )
setvect( irqAddr, oldhandler );
oldhandler = 0;
portAddr = aPort;
irqAddr = aIRQ;
picMask = aMask;
oldhandler = getvect( irqAddr );
}
int ComDef::setCombuf( combuf *cb )
{
void interrupt far (*handler)(...);
if( owner != 0 ) return 0;
if( irqAddr == 0x0B )
handler = combuf::handler0x0B;
else if( irqAddr == 0x0C )
handler = combuf::handler0x0C;
else
return 0;
owner = cb;
outportb( portAddr+MCR, 0 );
outportb( portAddr+IER, 0 );
outportb( portAddr+LCR, inportb(portAddr+LCR) & 0x3F );
for( int i = 0; i < 7; i++ )
inportb( portAddr+i );
setvect( irqAddr, handler );
outportb( 0x21, (inportb(0x21) & ~picMask) );
outportb( portAddr+MCR, GP02 );
outportb( portAddr+IER, 0x0F );
return 1;
}
void ComDef::clrCombuf()
{
if( owner == 0 ) return;
if( irqAddr != 0x0B && irqAddr != 0x0C )
return;
outportb( 0x21, (inportb(0x21) | picMask) );
outportb( portAddr+MCR, 0 );
outportb( portAddr+IER, 0 );
setvect( irqAddr, oldhandler );
owner = 0;
}
ComDef combuf::def[] = { 0, 1, 2, 3 };
void interrupt far combuf::handler0x0B(...)
{
combuf *owner;
int i, port, cause, data;
for( i = 0; i < NUMBEROFPORTS; i++ )
if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0B )
{
port = combuf::def[i].portAddr;
cause = inportb( port+IIR ) & 0x0F;
if( (cause & 1) == 0 )
{
if( cause == READFULL ) data = inportb( port );
else if( cause == LINEFAIL ) data = inportb( port+LSR );
else if( cause == MODEMFAIL ) data = inportb( port+MSR );
outportb( 0x20, 0x20 );
owner->handleIRQ( port, cause, data );
return;
}
}
outportb( 0x20, 0x20 );
}
void interrupt far combuf::handler0x0C(...)
{
combuf *owner;
int i, port, cause, data;
for( i = 0; i < NUMBEROFPORTS; i++ )
if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0C )
{
port = combuf::def[i].portAddr;
cause = inportb( port+IIR ) & 0x0F;
if( (cause & 1) == 0 )
{
if( cause == READFULL ) data = inportb( port );
else if( cause == LINEFAIL ) data = inportb( port+LSR );
else if( cause == MODEMFAIL ) data = inportb( port+MSR );
outportb( 0x20, 0x20 );
owner->handleIRQ( port, cause, data );
return;
}
}
outportb( 0x20, 0x20 );
}
void combuf::handleIRQ( int port, int cause, int data )
{
if( cause == READFULL )
insertc( data );
else if( cause == XMTEMPTY )
{
int ch = extractc();
if( ch != EOF )
{
if( ibdelay_ != 0 || (ch == '\r' && ildelay_ != 0) )
{
long l = (ch == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
int n = inportb( 0x21 );
outportb( 0x21, n | 0x18 );
enable();
Timer timer;
while( timer.elapsed() < l );
disable();
outportb( 0x21, n );
}
outportb( port, ch );
}
}
else if( cause == LINEFAIL )
errFlags |= ( data & (OR | FE | PE | BI) );
}
combuf::combuf( char *b, int inlen, int outlen ) : streambuf( b, inlen+outlen )
{
inSize = inlen;
errFlags = 0;
options = 0;
offs_ = EOF;
setTimeout( 300 );
setInterCharDelay( 0 );
setInterLineDelay( 0 );
}
combuf::combuf()
{
inSize = 0;
errFlags = 0;
options = 0;
offs_ = EOF;
setTimeout( 300 );
setInterCharDelay( 0 );
setInterLineDelay( 0 );
}
combuf::~combuf()
{
setPort();
}
streambuf *combuf::setbuf( signed char *b, int len )
{
streambuf::setbuf( b, len );
inSize = len/2;
return this;
}
combuf *combuf::setbuf( char *b, int inlen, int outlen )
{
streambuf::setbuf( b, inlen+outlen );
inSize = inlen;
return this;
}
int combuf::underflow()
{
Timer timer;
if( offs_ == EOF ) return EOF;
if( in_avail() == 0 )
{
while( timer.elapsed() < timeout_ && in_avail() == 0 );
if( in_avail() == 0 )
{
errFlags |= TIMEOUT;
return EOF;
}
}
return (unsigned char) *(gptr());
}
int combuf::do_sputn( const char *b, int len )
{
Timer timer;
long l;
int i, port, n;
if( offs_ == EOF || base() == 0 || len <= 0)
return 0;
if( pptr() == 0 )
{
port = def[offs_].portAddr;
if( (options & HW_HANDSHAKE) != 0 )
assertToPort( MCR, RTS );
if( ibdelay_ != 0 || (*b == '\r' && ildelay_ != 0) )
{
l = (*b == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
timer.start();
while( timer.elapsed() < l );
}
timer.start();
while( TESTPORTBIT(port+LSR,TBE) == 0 &&
( (options & HW_HANDSHAKE) == 0 || TESTPORTBIT(port+MSR,CTS) != 0 ) )
if( timer.elapsed() >= timeout_ )
{
errFlags |= TIMEOUT;
return 0;
}
if( len == 1 )
{
outportb( port, *b );
return 1;
}
n = blen()-inSize;
setp( base()+inSize, ebuf() );
if( n >= len-1 )
{
memcpy( pptr(), b+1, len-1 );
pbump( len-1 );
outportb( port, *b );
return len;
}
memcpy( pptr(), b+1, n );
pbump( n );
outportb( port, *b );
b += (n+1);
for( i = n+1; i < len && sputc(*b++) != EOF; i++ )
i++;
return i;
}
else
return streambuf::do_sputn( b, len );
}
int combuf::overflow( int c )
{
char b = c;
return do_sputn( &b, 1 );
}
void combuf::setBaud( long baud )
{
if( offs_ == EOF || baud < 50 || baud > 115200L )
return;
unsigned u = (unsigned) ( 115200L / baud );
assertToPort( LCR, DLAB );
outportb( def[offs_].portAddr, (u & 0xFF) );
outportb( def[offs_].portAddr+1, ((u >> 8) & 0xFF) );
unassertToPort( LCR, DLAB );
}
void combuf::setParity( int parity )
{
int i;
if( offs_ == EOF ) return;
else if( parity == NO_PARITY ) i = 0;
else if( parity == ODD_PARITY ) i = 0x08;
else if( parity == EVEN_PARITY ) i = 0x18;
else return;
outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xC7) | i );
}
void combuf::setBits( int bits )
{
if( offs_ == EOF || bits < 6 || bits > 8 ) return;
bits -= 5;
outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFC) | bits );
}
void combuf::setStopBits( int bits )
{
if( offs_ == EOF || bits < 1 || bits > 2 ) return;
bits = (bits-1)*4;
outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFB) | bits );
}
void combuf::setParams( CommProtocol& p )
{
if( offs_ == EOF ) return;
if( p.baud < 50L || p.baud > 115200L ) return;
if( p.parity < NO_PARITY || p.parity > EVEN_PARITY ) return;
if( p.bits < 6 || p.bits > 8 ) return;
if( p.stopBits != 1 && p.stopBits != 2 ) return;
setBaud( p.baud );
setParity( p.parity );
setBits( p.bits );
setStopBits( p.stopBits );
}
void combuf::setTimeout( unsigned long l )
{
timeout_ = timeToTicks( l );
}
void combuf::setInterCharDelay( unsigned long l )
{
ibdelay_ = timeToTicks( l );
}
void combuf::setInterLineDelay( unsigned long l )
{
ildelay_ = timeToTicks( l );
}
void combuf::setPort( int p )
{
if( offs_ != EOF )
def[offs_].clrCombuf();
if( p